package com.example.lihongwei42.bluetoothuitls;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;

public class AudioSwitchUtils {
    public static final String TAG = AudioSwitchUtils.class.getSimpleName();
    private EquipStateReceiver equipStateReceiver;
    private BluetoothAdapter mBluetoothAdapter;
    private AudioManager mAudioManager;
    private boolean isBtAudioOpened;//标志蓝牙通道是否打开(因为实际上会有蓝牙显示连接但声音通道切不过去的情况)
    public static int SPEAKER = 0;
    public static int BLUETOOTH = 1;
    public static int WIRED_HEADSET = 2;
    public static int RECEIVER = 3;
    private TelephonyManager mTelephonyManager = null;

    private int currentChannel = RECEIVER;//当前程序的默认播放通道
    private AudioManager.OnAudioFocusChangeListener afChangeListener;

    public interface OnHandsetStateChangeListener {
        void onBtOff();

        void onBtConnected();

        void onBtDisconnected();

        void onBtAudioConnected();

        void onBtAudioDisconnected(boolean setToBt, boolean btAlive);

        void onHeatSetConnectLoss();

        void onWiredHeadSetOut();

        void onWiredHeadSetIn();
        
        void onAudioFocusLossTransient();

        void onAudioFocusLoss();

        void onAudioFocusGain(boolean setToBt, boolean btAlive);
    }

    private OnHandsetStateChangeListener onHandsetStateChangeListener;

    private class EquipStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {//蓝牙打开或关闭状态
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                if (state == BluetoothAdapter.STATE_OFF || state == BluetoothAdapter.STATE_TURNING_OFF) {
                    Log.d(TAG, "蓝牙未打开或者已关闭");
                    if (onHandsetStateChangeListener != null)
                        onHandsetStateChangeListener.onBtOff();
                }
            } else if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {//比bluetoothHeadset的广播要早一点
                Log.d(TAG, "有线耳机和蓝牙设备断开都会发这个广播");
                isBtAudioOpened = false;
                if (onHandsetStateChangeListener != null)
                    onHandsetStateChangeListener.onHeatSetConnectLoss();
            } else if (BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED.equals(intent.getAction())) {
                int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, 0);
                if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
                    Log.d(TAG, "BluetoothHeadset设备音频已连接");
                    isBtAudioOpened = true;
                    currentChannel = BLUETOOTH;
                    if (onHandsetStateChangeListener != null)
                        onHandsetStateChangeListener.onBtAudioConnected();
                } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
                    //MODE为MODE_IN_COMMUNICATION时切换信道会发这个广播，微信语音播放完也会出发这个广播
                    Log.d(TAG, "BluetoothHeadset设备音频断开");
                    Log.d(TAG, "当前蓝牙设备连接状态:" + ((isBluetoothEnabled() && isBluetoothConnected()) ? "已连接" : "未连接"));
                    Log.e(TAG, "mode=" + mAudioManager.getMode());
                    if (onHandsetStateChangeListener != null)
                        onHandsetStateChangeListener.onBtAudioDisconnected(currentChannel == BLUETOOTH, isBluetoothEnabled() && isBluetoothConnected());
                }
            } else if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
                int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, 0);
                if (state == BluetoothHeadset.STATE_DISCONNECTED) {
                    Log.d(TAG, "BluetoothHeadset设备未连接或已断开连接");
                    if (onHandsetStateChangeListener != null)
                        onHandsetStateChangeListener.onBtDisconnected();
                } else if (state == BluetoothHeadset.STATE_CONNECTED) {
                    //蓝牙中途断开后再连接上尝试开启蓝牙音频通道，如果成功打开会发送STATE_AUDIO_CONNECTED的广播，触发isBtAudioOpened=true
                    //此时再切换通道就会知道是否切换成功
                    mAudioManager.startBluetoothSco();
                    mAudioManager.setBluetoothScoOn(true);

                    Log.d(TAG, "BluetoothHeadset设备已连接");
                    if (onHandsetStateChangeListener != null)
                        onHandsetStateChangeListener.onBtConnected();
                }
            } else if (Intent.ACTION_HEADSET_PLUG.equals(intent.getAction())) {
                int state = intent.getIntExtra("state", 0);
                if (state == 1) {//插入耳机
                    Log.d(TAG, "耳机已接入");
                    if (onHandsetStateChangeListener != null)
                        onHandsetStateChangeListener.onWiredHeadSetIn();
                } else if (state == 0) {//拔出耳机
                    Log.d(TAG, "耳机未接入");
                    if (onHandsetStateChangeListener != null)
                        onHandsetStateChangeListener.onWiredHeadSetOut();
                }
            }/* else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(intent.getAction())) {//6.0以上需要动态申请权限
                Log.d(TAG, "收到ACTION_PHONE_STATE_CHANGED广播");
                int state = mTelephonyManager.getCallState();
                if (state == TelephonyManager.CALL_STATE_IDLE) {
                    Log.d(TAG, "电话挂断");
                    if (currentChannel == BLUETOOTH)
                        switchToBluetoothHeadset();
                }
            }*/
        }
    }

    private static AudioSwitchUtils instance;

    public static AudioSwitchUtils getInstance() {
        if (instance == null) {
            synchronized (AudioSwitchUtils.class) {
                if (instance == null)
                    instance = new AudioSwitchUtils();
            }
        }
        return instance;
    }

    private AudioSwitchUtils() {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        equipStateReceiver = new EquipStateReceiver();
    }

    public AudioSwitchUtils init(Context mContext) {
        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);

        //蓝牙状态广播监听
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(Intent.ACTION_HEADSET_PLUG);
        filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
        filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
        filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        //  filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
        mContext.getApplicationContext().registerReceiver(equipStateReceiver, filter);

        if (mAudioManager != null) {
            mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);//如果不设置默认的mode是MODE_NORMAL
            if (isBluetoothConnected()) {
                mAudioManager.startBluetoothSco();
                mAudioManager.setBluetoothScoOn(true);
            }
        }
        afChangeListener = new AudioManager.OnAudioFocusChangeListener() {
            @Override
            public void onAudioFocusChange(int focusChange) {
                if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
                    Log.d(TAG, "暂时失去焦点");
                    if (onHandsetStateChangeListener != null)
                        onHandsetStateChangeListener.onAudioFocusLossTransient();
                } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
                    Log.d(TAG, "获得焦点");
                    Log.e(TAG, "mode=" + mAudioManager.getMode());
                    if (onHandsetStateChangeListener != null)
                        onHandsetStateChangeListener.onAudioFocusGain(currentChannel == BLUETOOTH, isBluetoothEnabled() && isBluetoothConnected());
                } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
                    Log.d(TAG, "永久失去焦点");
                    if (onHandsetStateChangeListener != null)
                        onHandsetStateChangeListener.onAudioFocusLoss();
                }
            }
        };
        int result = mAudioManager.requestAudioFocus(afChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            Log.d(TAG, "获取到音频焦点");
        }
        return instance;
    }

    public void setOnHandsetChangeListener(OnHandsetStateChangeListener listener) {
        this.onHandsetStateChangeListener = listener;
    }

    private void showConfirmDialog(final Context mContext) {
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setTitle("跳转到蓝牙设置页面？");
        builder.setPositiveButton("好的", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                goConnectBleDevices(mContext);
            }
        });
        builder.create().show();
    }

    //跳转到蓝牙设置界面
    public void goConnectBleDevices(Context context) {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_BLUETOOTH_SETTINGS);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (context instanceof Activity)
            context.startActivity(intent);
    }


    public boolean enableBluetooth() {
        if (mBluetoothAdapter == null) {
            Log.d(TAG, "此设备不支持蓝牙");
            return false;
        }
        return mBluetoothAdapter.enable();
    }

    public boolean disableBluetooth() {
        if (mBluetoothAdapter == null) {
            Log.d(TAG, "此设备不支持蓝牙");
            return false;
        }
        return mBluetoothAdapter.disable();
    }

    public boolean isBluetoothEnabled() {
        if (mBluetoothAdapter == null) {
            Log.d(TAG, "此设备不支持蓝牙");
            return false;
        }
        return mBluetoothAdapter.isEnabled();
    }

    public boolean isBluetoothConnected() {
        if (mBluetoothAdapter == null) {
            Log.d(TAG, "此设备不支持蓝牙");
            return false;
        }
        int a2dp = mBluetoothAdapter.getProfileConnectionState(BluetoothProfile.A2DP);
        int headset = mBluetoothAdapter.getProfileConnectionState(BluetoothProfile.HEADSET);
        return a2dp == BluetoothProfile.STATE_CONNECTED || headset == BluetoothProfile.STATE_CONNECTED;
    }

    //有线耳机是否连接
    public boolean isWiredHeadsetConnected() {
        if (mAudioManager == null) {
            Log.d(TAG, "请先初始化工具");
            return false;
        }
        boolean isWiredHeadsetConnected = false;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            isWiredHeadsetConnected = mAudioManager.isWiredHeadsetOn();
        } else {
            AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
            for (AudioDeviceInfo device : devices) {
                if (device.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES) {
                    isWiredHeadsetConnected = true;
                    break;
                }
            }
        }
        Log.d(TAG, isWiredHeadsetConnected ? "耳机已接入" : "耳机未接入或已拔出");
        return isWiredHeadsetConnected;
    }

    /**
     * 切换到扬声器
     */
    public void switchToSpeaker() {
        if (mAudioManager == null) {
            Log.d(TAG, "请先初始化工具");
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        else
            mAudioManager.setMode(AudioManager.MODE_IN_CALL);
        mAudioManager.setSpeakerphoneOn(true);
        mAudioManager.stopBluetoothSco();
        mAudioManager.setBluetoothScoOn(false);
        currentChannel = SPEAKER;
    }

    /**
     * 切换到蓝牙
     */
    public boolean switchToBluetoothHeadset() {
        if (mAudioManager == null) {
            Log.d(TAG, "请先初始化工具");
            return false;
        }
        if (!isBluetoothConnected())
            return false;
        if (mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE && mAudioManager.getMode() == AudioManager.MODE_IN_CALL) {
            Log.d(TAG, "当前处于普通电话通话状态");
            return false;
        }
        Log.d(TAG,"切换到蓝牙通道");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        else
            mAudioManager.setMode(AudioManager.MODE_IN_CALL);
        mAudioManager.setSpeakerphoneOn(false);
        mAudioManager.startBluetoothSco();
        mAudioManager.setBluetoothScoOn(true);
        currentChannel = BLUETOOTH;
        //设置音量，解决有些机型切换后没声音或者声音突然变大的问题
//        mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
//                mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), AudioManager.FX_KEY_CLICK);
        return isBtAudioOpened;
    }

    /**
     * 切换到有线耳机
     */
    public void switchToWiredHeadset() {
        if (mAudioManager == null) {
            Log.d(TAG, "请先初始化工具");
            return;
        }
        mAudioManager.stopBluetoothSco();
        mAudioManager.setBluetoothScoOn(false);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        else
            mAudioManager.setMode(AudioManager.MODE_IN_CALL);
        mAudioManager.setSpeakerphoneOn(false);
        currentChannel = WIRED_HEADSET;
    }

    /**
     * 切换到听筒
     */
    public void switchToReceiver() {
        if (mAudioManager == null) {
            Log.d(TAG, "请先初始化工具");
            return;
        }
        mAudioManager.stopBluetoothSco();
        mAudioManager.setBluetoothScoOn(false);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        else
            mAudioManager.setMode(AudioManager.MODE_IN_CALL);
        mAudioManager.setSpeakerphoneOn(false);
        currentChannel = RECEIVER;
    }

    public boolean isSpeakerPlaying() {
        if (mAudioManager == null) {
            Log.d(TAG, "请先初始化工具");
            return false;
        }
        return mAudioManager.isSpeakerphoneOn();
    }

    public boolean isBluetoothPlaying() {
        if (mAudioManager == null) {
            Log.d(TAG, "请先初始化工具");
            return false;
        }
        return mAudioManager.isBluetoothScoOn();
    }

    //当前是否为听筒播放
    public boolean isReceiverPlaying() {
        if (mAudioManager == null) {
            Log.d(TAG, "请先初始化工具");
            return false;
        }
        return mAudioManager.getMode() == AudioManager.MODE_IN_COMMUNICATION && !mAudioManager.isBluetoothScoOn()
                && !isWiredHeadsetConnected() && !mAudioManager.isSpeakerphoneOn();
    }

    public boolean isWiredHeadsetPlaying() {
        if (mAudioManager == null) {
            Log.d(TAG, "请先初始化工具");
            return false;
        }
        return mAudioManager.getMode() == AudioManager.MODE_IN_COMMUNICATION && !mAudioManager.isBluetoothScoOn()
                && isWiredHeadsetConnected() && !mAudioManager.isSpeakerphoneOn();
    }


    //释放资源
    public void release(Context context) {
        context.getApplicationContext().unregisterReceiver(equipStateReceiver);
        //将audio设置还原
        if (mAudioManager != null) {
            mAudioManager.setSpeakerphoneOn(false);
            mAudioManager.setMode(AudioManager.MODE_NORMAL);
            mAudioManager.stopBluetoothSco();
            mAudioManager.setBluetoothScoOn(false);
            if (afChangeListener != null)
                mAudioManager.abandonAudioFocus(afChangeListener);
        }
        instance = null;
    }
}
